package jp.sourceforge.akjrcp.psp;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.flvtools.basic.FLVToolsPage;
import jp.sourceforge.akjrcp.flvtools.explorer.ThumbnailManager;
import jp.sourceforge.akjrcp.psp.commands.AbstractIOCommand;
import jp.sourceforge.akjrcp.psp.commands.PSPCopyCommand;
import jp.sourceforge.akjrcp.psp.commands.PSPDeleteCommand;
import jp.sourceforge.akjrcp.psp.commands.PSPMoveCommand;
import jp.sourceforge.akjrcp.ui.DirectoryList;
import jp.sourceforge.akjrcp.util.FileNameUtils;
import jp.sourceforge.akjrcp.util.ProgressMonitorUtils;
import jp.sourceforge.akjrcp.util.StatusBarUtils;
import jp.sourceforge.akjrcp.util.image.ImageUtils;

import org.apache.commons.io.FileSystemUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.draw2d.ActionEvent;
import org.eclipse.draw2d.ActionListener;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.FlowLayout;
import org.eclipse.draw2d.FrameBorder;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.InputEvent;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;




public class PSPSyncView extends ViewPart{
	public static Log log=LogFactory.getLog(PSPSyncView.class);
	
	public static final String ID = PSPSyncView.class.getName();


	
	protected static Image noImage = new Image(Display.getCurrent(),
			DirectoryList.class.getClassLoader().getResourceAsStream(
					"jp/sourceforge/akjrcp/psp/resource/"+Messages.getString("pspsync.no_image")));

	private Figure hdFigure;
	private Figure hdListFigure;
	private FigureCanvas hdCanvas;
	
	
	private Figure pspFigure;
	private Figure pspListFigure;
	private FigureCanvas pspCanvas;
	
	private boolean monitorPSPDirectory=true;
	private boolean monitorHDDirectory=true;
	private int pspMonitorSleeptime=3000;
	private int hdMonitorSleeptime=5000;
	private File hdDir;
	private File[] hdMP4Files;
	
	
	private File pspDir;
	private File[] pspMP4Files;
	
	private int pspDirectoryStatus;
	
	private DirectoryInfomation hdInfo;
	private DirectoryInfomation pspInfo;
	
	private CCombo directoryPaths;
	private org.eclipse.swt.widgets.Button pspDirPath;
	
	private String lastPSPDirectoryInfo="";
	private String lastHDDirectoryInfo="";
	public static final int PSP_VIDEO_EXIST=1;
	public static final int PSP_NOTFOUND=0;
	public static final int PSP_VIDEO_NOTFOUND=2;
	
	public static final int ACTION_NONE=0;
	public static final int ACTION_COPY=1;
	public static final int ACTION_MOVE=2;
	public static final int ACTION_COPY_OVERWRITE=3;
	public static final int ACTION_MOVE_OVERWRITE=4;
	public static final int ACTION_DELETE=5;
	
	public static final String LABEL_ACTION_NONE="";
	public static final String LABEL_ACTION_COPY=Messages.getString("pspsync.action_copy");
	public static final String LABEL_ACTION_MOVE=Messages.getString("pspsync.action_move");
	public static final String LABEL_ACTION_COPY_OVERWRITE=Messages.getString("pspsync.action_copy_overwrite");
	public static final String LABEL_ACTION_MOVE_OVERWRITE=Messages.getString("pspsync.action_move_overwrite");
	public static final String LABEL_ACTION_DELETE=Messages.getString("pspsync.action_delete");
	public static final String LABEL_ACTION_PLAY=Messages.getString("pspsync.action_play");
	public static final String LABEL_ACTION_OPEN=Messages.getString("pspsync.action_open");

	private MovieActionPopup hdMovieActionPopup,pspMovieActionPopup;
	
	ExplorerPathChange explorerPathChange;

	private Button syncButton;
	 boolean executing;
	 PSPIOCommand currentCommand;
	 
	 
	 IProgressMonitor progressMonitor;
	 
	 
	public class DirectoryInfomation extends Composite{
private long freeSpace;
private long totalSpace;
private long additionalSpace;

private org.eclipse.swt.widgets.Label label;
private Color normalColor=new Color(null,0,0,0);
private Color overColor=new Color(null,255,0,0);

		public DirectoryInfomation(Composite arg0, int arg1) {
			super(arg0, arg1);
		
			this.setLayout(new FillLayout());
			label=new org.eclipse.swt.widgets.Label(this,SWT.NULL);
		}
		public boolean isOverSize(){
			return freeSpace*1024<additionalSpace;
		}
		public void updateLabel(){
			if(!label.isDisposed()){
			//for sefaty for after view closed.
			if(freeSpace>0){
				if(isOverSize()){
					label.setForeground(overColor);
					
				}else{
					label.setForeground(normalColor);
				}
				//"total:"+totalSpace+ current total not supported.
				BigDecimal bd = new BigDecimal((double)freeSpace/1000);
				double free = bd.setScale(1, BigDecimal.ROUND_HALF_UP)
				                  .doubleValue();
				
				BigDecimal bd2 = new BigDecimal((double)additionalSpace/1000/1000);//addtional is bytes
				
				double add = bd2.setScale(1, BigDecimal.ROUND_HALF_UP)
				                  .doubleValue();
				
				String text=Messages.getString("pspsync.free_space")+":"+free+" MBytes";
				if(additionalSpace!=0){
					text+=Messages.getString("pspsync.add_space")+":"+add+" MBytes";
				}
				label.setText(text);
			}else{
				label.setText("");
			}
			}
		}
		public long getAdditionalSpace() {
			return additionalSpace;
		}
		public void setAdditionalSpace(long additionalSpace) {
			this.additionalSpace = additionalSpace;
			updateLabel();
		}
		public long getFreeSpace() {
			return freeSpace;
			
		}
		public void setFreeSpace(long freeSpace) {
			this.freeSpace = freeSpace;
			updateLabel();
		}
		public long getTotalSpace() {
			return totalSpace;
		}
		public void setTotalSpace(long totalSpace) {
			this.totalSpace = totalSpace;
			updateLabel();
		}
		
	}
	public boolean makeThumb(){
		return false;
	}
	
	public class UpdateSelection extends Thread{
		public void run(){
			updateSelection();
		}
	}
	public void updateSelection(){
		updateDirectoryInfo();
		updateSyncButton();
	}
	
	public void updateSyncButton(){
		
		boolean enabled=false;
		MP4ThumbnailFigure hdFigures[]=getHDMP4Figure();
		for (int i = 0; i < hdFigures.length; i++) {
			if(hdFigures[i].isSelection() && hdFigures[i].getAction()!=ACTION_NONE){
				enabled=true;
				break;
			}
		}
		
		MP4ThumbnailFigure pspFigures[]=getPSPMP4Figures();
		for (int i = 0; i < pspFigures.length; i++) {
			if(pspFigures[i].isSelection() && pspFigures[i].getAction()!=ACTION_NONE){
				enabled=true;
				break;
			}
		}
	
	//log.info("enabled:"+enabled);
	
	if(hdInfo.isOverSize()){
		enabled=false;
	}
	
	if(pspInfo.isOverSize()){
		enabled=false;
	}
	
	//log.info("over:"+enabled);
	
	
	
	if(!commandAvailable(hdInfo.getFreeSpace()*1024,pspInfo.getFreeSpace()*1024,getCommands())){
		enabled=false;
	}
	
	//log.info("command:"+enabled);
	if(!syncButton.isDisposed()){
		syncButton.setEnabled(enabled);
		}
	}
	
	public PSPIOCommand[] getCommands(){
		MP4ThumbnailFigure hdFigures[]=getHDMP4Figure();
		MP4ThumbnailFigure pspFigures[]=getPSPMP4Figures();
		
		List commandList=new ArrayList();
		for (int i = 0; i < hdFigures.length; i++) {
			if(hdFigures[i].isSelection() && hdFigures[i].getAction()!=ACTION_NONE){
				commandList.add(toCommand(hdFigures[i]));
			}
		}
		
		for (int i = 0; i < pspFigures.length; i++) {
			if(pspFigures[i].isSelection() && pspFigures[i].getAction()!=ACTION_NONE){
				commandList.add(toCommand(pspFigures[i]));
			}
		}
		return (PSPIOCommand[]) commandList.toArray(new PSPIOCommand[commandList.size()]);
	}
	
	public PSPIOCommand toCommand(MP4ThumbnailFigure figure){
		
		if(figure.isSelection() && figure.getAction()!=ACTION_NONE){
			File toDir;
			if(figure.isOnHD()){
				toDir=pspDir;
			}else{
				toDir=hdDir;
			}
			PSPIOCommand command=null;
			if(figure.getAction()==ACTION_COPY){
				command=new PSPCopyCommand(figure.getMp4File(),new File(toDir,figure.getMp4File().getName()),false);
				
			}
			else if(figure.getAction()==ACTION_MOVE){
				command=new PSPMoveCommand(figure.getMp4File(),new File(toDir,figure.getMp4File().getName()),false);
				
			}
				else if(figure.getAction()==ACTION_COPY_OVERWRITE){
				command=new PSPCopyCommand(figure.getMp4File(),new File(toDir,figure.getMp4File().getName()),true);
				
				}
				else if(figure.getAction()==ACTION_MOVE_OVERWRITE){
				command=new PSPMoveCommand(figure.getMp4File(),new File(toDir,figure.getMp4File().getName()),true);
				
				}
				else if(figure.getAction()==ACTION_DELETE){
				
				command= new PSPDeleteCommand(figure.getMp4File());
				}
			if(command!=null){
				if(figure.isOnHD()){
					command.setPSPSrc(false);
				}else{
					command.setPSPSrc(true);
				}
				return command;
			}else{
				log.warn(""+figure.getAction());
				return null;//never happend
			}
		}else{
			return null;
		}
	}
	
	
	public boolean commandAvailable(long freeHD,long freePSP,PSPIOCommand[] commands){
		
		List arrayList=new ArrayList();
		for (int i = 0; i < commands.length; i++) {
			arrayList.add(commands[i]);
		}
		
		while(arrayList.size()>0){
			boolean excused=false;
			for (int i = 0; i < arrayList.size(); i++) {
				PSPIOCommand command=(PSPIOCommand)arrayList.get(i);
				long space;
				if(command.isPSPSrc()){
					space=freeHD;
				}else{
					space=freePSP;
				}
				if(availableCommand(command, space)){
					excused=true;
					arrayList.remove(command);
					//log.info(command);//debug;
					break;
				}
			}
			
			if(excused==false){
				//command faild.
				return false;
			}
		}
		
		return true;
	}
	
	private boolean availableCommand(PSPIOCommand command,long destSpace){
		if(command instanceof PSPDeleteCommand){
			return true;
		}else{
			if(((AbstractIOCommand)command).isOverwrite()){
				return destSpace>command.getSrcFile().length()-command.getDestFile().length();
			}else{
				return destSpace>command.getSrcFile().length();
			}
		}
	}
	
	public void unselectPSPFile(String name){
		MP4ThumbnailFigure pspFigures[]=getPSPMP4Figures();
				
				for (int i = 0; i < pspFigures.length; i++) {
					if(pspFigures[i].isSelection()){
						if(pspFigures[i].getMp4File().getName().toLowerCase().equals(name.toLowerCase())){
							pspFigures[i].setSelection(false);
							updateDirectoryInfo();
							break;
						}
					}
				}
			}
	
	public void unselectHdFile(String name){
MP4ThumbnailFigure hdFigures[]=getHDMP4Figure();
		
		for (int i = 0; i < hdFigures.length; i++) {
			if(hdFigures[i].isSelection()){
				if(hdFigures[i].getMp4File().getName().toLowerCase().equals(name.toLowerCase())){
					hdFigures[i].setSelection(false);
					updateDirectoryInfo();
					break;
				}
			}
		}
	}
	public void updateDirectoryInfo(){
		if(hdDir==null || pspDir==null){
			return;
		}
		long hdAdd=0;
		long pspAdd=0;
		MP4ThumbnailFigure hdFigures[]=getHDMP4Figure();
		
		for (int i = 0; i < hdFigures.length; i++) {
			if(hdFigures[i].isSelection()){
				switch(hdFigures[i].getAction()){
				case ACTION_COPY:
					pspAdd+=hdFigures[i].getFileSize();
					break;
				case ACTION_MOVE:
					pspAdd+=hdFigures[i].getFileSize();
					hdAdd-=hdFigures[i].getFileSize();
					break;
				case ACTION_COPY_OVERWRITE:
					pspAdd+=hdFigures[i].getFileSize();
					pspAdd-=getOverwritedFile(hdFigures[i].getMp4File(),pspMP4Files).length();
					break;
				case ACTION_MOVE_OVERWRITE:
					pspAdd+=hdFigures[i].getFileSize();
					hdAdd-=hdFigures[i].getFileSize();
					pspAdd-=getOverwritedFile(hdFigures[i].getMp4File(),pspMP4Files).length();
					break;
				case ACTION_DELETE:
					hdAdd-=hdFigures[i].getFileSize();
					break;
				
				}
			}
		}
		
		
		//TODO check it.
		MP4ThumbnailFigure pspFigures[]=getPSPMP4Figures();
		//log.info(pspFigures.length);
		for (int i = 0; i < pspFigures.length; i++) {
			if(pspFigures[i].isSelection()){
				switch(pspFigures[i].getAction()){
				case ACTION_COPY:
					hdAdd+=pspFigures[i].getFileSize();
					break;
				case ACTION_MOVE:
					hdAdd+=pspFigures[i].getFileSize();
					pspAdd-=pspFigures[i].getFileSize();
					break;
				case ACTION_COPY_OVERWRITE:
					hdAdd+=pspFigures[i].getFileSize();
					hdAdd-=getOverwritedFile(pspFigures[i].getMp4File(),hdMP4Files).length();
					break;
				case ACTION_MOVE_OVERWRITE:
					hdAdd+=pspFigures[i].getFileSize();
					pspAdd-=pspFigures[i].getFileSize();
					hdAdd-=getOverwritedFile(pspFigures[i].getMp4File(),hdMP4Files).length();
					break;
				case ACTION_DELETE:
					pspAdd-=pspFigures[i].getFileSize();
					break;
				
				}
			}
		}
		
		hdInfo.setAdditionalSpace(hdAdd);
		pspInfo.setAdditionalSpace(pspAdd);
		
	}
	
	public File getOverwritedFile(File file,File list[]){
	for (int i = 0; i < list.length; i++) {
		if(file.getName().toLowerCase().equals(list[i].getName().toLowerCase())){
			return list[i];
		}
	}	
	return null;
	}
	
	
	public void openPSPFolder(){
		if(pspDir==null){
			return;
		}
		
		Runtime r=Runtime.getRuntime();
		try {
			r.exec(new String[]{"explorer",pspDir.getAbsolutePath()});
		} catch (IOException e) {
			
			e.printStackTrace();
		}
	}
	
	public void createPartControl(Composite parent) {
		parent.setLayout(new GridLayout(2, true));
		
		syncButton = new Button(parent,SWT.NONE);
		
		syncButton.setText(Messages.getString("pspsync.exec"));
		GridData gd=new GridData();
		gd.heightHint=40;
		gd.horizontalSpan=2;
		gd.horizontalAlignment=SWT.CENTER;
		gd.minimumWidth=300;
		//gd.minimumHeight=40;
		//gd.grabExcessVerticalSpace=true;
		gd.grabExcessHorizontalSpace=true;
		syncButton.setLayoutData(gd);
		syncButton.setEnabled(false);//default false.
		syncButton.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			public void widgetSelected(SelectionEvent e) {
				if(executing){
					log.info("call ancel");
					cancel();
				}else{
					log.info("call sync");
					sync();
				}
				
				
			}
			
		});
		
		
		directoryPaths=new CCombo(parent,SWT.READ_ONLY);
		explorerPathChange=new ExplorerPathChange();
		directoryPaths.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		pspDirPath=new org.eclipse.swt.widgets.Button(parent,SWT.NONE);
		pspDirPath.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		pspDirPath.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
			}

			public void widgetSelected(SelectionEvent e) {
				openPSPFolder();
			}
			
		});
		
		hdInfo=new DirectoryInfomation(parent,SWT.BORDER);
		hdInfo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		pspInfo=new DirectoryInfomation(parent,SWT.BORDER);
		pspInfo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		Composite hdComposite=new Composite(parent,SWT.BORDER);
		hdComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		
		
		//hdComposite.setLayout(layout1);
		hdComposite.setLayout(new FillLayout());
		
		hdCanvas = new FigureCanvas(hdComposite);
		hdCanvas.addMouseListener(new MouseListener(){

			public void mouseDoubleClick(MouseEvent e) {
				
			}

			public void mouseDown(MouseEvent e) {
							
							hdMovieActionPopup.setCopyEnabled(false);
							hdMovieActionPopup.setMoveEnabled(false);
							hdMovieActionPopup.setCopyOverwriteEnabled(false);
							hdMovieActionPopup.setMoveOverwriteEnabled(false);
							hdMovieActionPopup.setDeleteEnabled(false);
							hdMovieActionPopup.setPlayEnabled(false);
							if(hdDir!=null && hdDir.exists()){
								hdMovieActionPopup.setOpenEnabled(true);
							}else{
								hdMovieActionPopup.setOpenEnabled(false);
							}
						
			}

			public void mouseUp(MouseEvent e) {
				
			}
			
		});
		//hdCanvas.setLayoutData(new GridData(GridData.FILL_BOTH));
		hdFigure = new Figure();
		hdCanvas.setContents(hdFigure);
		hdFigure.setLayoutManager(new StackLayout());
		hdCanvas.addControlListener(new ResizeMonitor(hdFigure));
		
		hdMovieActionPopup = new MovieActionPopup(hdCanvas);
		hdMovieActionPopup.setHdDirectory(true);
		hdCanvas.setMenu(hdMovieActionPopup.getRootMenu());
		
		//openHDDirectory(new File("c:\\tmp\\mp4"));//for test
		
		//psp
		Composite pspComposite=new Composite(parent,SWT.BORDER);
		pspComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
		pspComposite.setLayout(new FillLayout());
		
		pspCanvas = new FigureCanvas(pspComposite);
		pspCanvas.addMouseListener(new MouseListener(){

			public void mouseDoubleClick(MouseEvent e) {
				
			}

			public void mouseDown(MouseEvent e) {
						
							pspMovieActionPopup.setCopyEnabled(false);
							pspMovieActionPopup.setMoveEnabled(false);
							pspMovieActionPopup.setCopyOverwriteEnabled(false);
							pspMovieActionPopup.setMoveOverwriteEnabled(false);
							pspMovieActionPopup.setDeleteEnabled(false);
							pspMovieActionPopup.setPlayEnabled(false);
							if(pspDir!=null && pspDir.exists()){
								pspMovieActionPopup.setOpenEnabled(true);
							}else{
								pspMovieActionPopup.setOpenEnabled(false);
							}
						
			}

			public void mouseUp(MouseEvent e) {
				
			}
			
		});
		//pspCanvas.setBackground(new Color(null,255,0,0));
		//pspCanvas.setLayoutData(new GridData(GridData.FILL_BOTH));
		pspFigure = new Figure();
		pspCanvas.setContents(pspFigure);
		pspFigure.setLayoutManager(new StackLayout());
		pspCanvas.addControlListener(new ResizeMonitor(pspFigure));
		
		pspMovieActionPopup = new MovieActionPopup(pspCanvas);
		pspMovieActionPopup.setHdDirectory(false);
		pspCanvas.setMenu(pspMovieActionPopup.getRootMenu());
		
		
		
		
		updateExplorerPaths();//directory
		openHDDirectory(new File(directoryPaths.getItem(directoryPaths.getSelectionIndex())));
		Akj_betasPlugin.getDefault().getPluginPreferences().addPropertyChangeListener( new SettingMonitor());
		
		
		new AutoPSPVideoDirectoryOpener().start();
		new AutoHDDirectoryOpener().start();
	}
	
	public boolean isPSPDirectoryAvailable(){
		return pspDir!=null;
	}
	
	public boolean isHDDirectoryAvailable(){
		return hdDir!=null;
	}
	
	public class UpdatePSPDir extends Thread{
		private File file;
		
		public UpdatePSPDir(File file){
			this.file=file;
			
		}
		public void run(){
			
				//log.info("update psp dir:"+file);
				if(!pspDirPath.isDisposed()){//for thread
				if(file!=null){
				pspDirPath.setText(file.getAbsolutePath());
				}else{
					pspDirPath.setText("");
				}
				}
			
		}
	}
	
	public MP4ThumbnailFigure findPSPFigure(File mp4file){
		MP4ThumbnailFigure ret=null;
		MP4ThumbnailFigure[] figures=getPSPMP4Figures();
		for (int i = 0; i < figures.length; i++) {
			if(figures[i].getMp4File().getAbsolutePath().toLowerCase().equals(mp4file.getAbsolutePath().toLowerCase())){
				ret=figures[i];
				break;
			}
		}
		return ret;
	}
	
	public MP4ThumbnailFigure findHDFigure(File mp4file){
		MP4ThumbnailFigure ret=null;
		MP4ThumbnailFigure[] figures=getHDMP4Figure();
		for (int i = 0; i < figures.length; i++) {
			if(figures[i].getMp4File().getAbsolutePath().toLowerCase().equals(mp4file.getAbsolutePath().toLowerCase())){
				ret=figures[i];
				break;
			}
		}
		return ret;
	}
	
	public class SetFreeSpace extends Thread{
		private File file;
		private DirectoryInfomation target;
		public SetFreeSpace(File file,DirectoryInfomation target){
			this.file=file;
			this.target=target;
		}
		public void run(){
			try {
				if(file==null || !file.exists()){
					target.setFreeSpace(0);
				}else{
				
				target.setFreeSpace(FileSystemUtils.freeSpaceKb(file.getAbsolutePath()));
				}
			} catch (IOException e) {
				
				e.printStackTrace();
			}
		}
	}
	public void updatePSPDir(File dir,boolean keepselect){
	//	log.info("update psp dir");
		if(dir==null || !dir.exists()){//when disconnected
		pspDir=null;
		pspMP4Files=null;
			PlatformUI.getWorkbench().getDisplay().syncExec(new UpdatePSPDir(null));
			PlatformUI.getWorkbench().getDisplay().syncExec(new SetFreeSpace(null,pspInfo));
		//	log.info("no psp dir");
		}else{
		File videoDir=new File(dir,"VIDEO");
		if(!videoDir.exists()){//maybe delete folder
			log.warn("no video folder");
			pspDir=null;
			pspMP4Files=null;
			PlatformUI.getWorkbench().getDisplay().syncExec(new UpdatePSPDir(null));
			PlatformUI.getWorkbench().getDisplay().syncExec(new SetFreeSpace(null,pspInfo));
			return;
			}
		File[] mp4=getMP4Files(videoDir);
		String data=toDirectoryInfo(videoDir,mp4);
		if(!lastPSPDirectoryInfo.equals(data)){
			PlatformUI.getWorkbench().getDisplay().syncExec(new UpdatePSPDir(videoDir));
			updatePSPFiles(videoDir,mp4,keepselect);
			lastPSPDirectoryInfo=data;
		}
			
			PlatformUI.getWorkbench().getDisplay().syncExec(new SetFreeSpace(videoDir,pspInfo));
		
		}
		PlatformUI.getWorkbench().getDisplay().syncExec(new UpdateSelection());
		
	}
	
	public File[] getMP4Files(File file){
		List fileList=new ArrayList();
		String list[]=file.list(new MP4FilenameFilter());
		if(list==null){
			log.warn("file.lise()==null:"+file);
			return new File[0];
		}
		for (int i = 0; i < list.length; i++) {
			File mp4File=new File(file,list[i]);
			if(mp4File.length()>0){//for valid mp4
				fileList.add(mp4File);
			}
		}
		return (File[]) fileList.toArray(new File[fileList.size()]);
	}
	private String toDirectoryInfo(File dir,File files[]){
		StringBuffer buffer=new StringBuffer();
		buffer.append(dir.getAbsolutePath());
		
		for (int i = 0; i < files.length; i++) {
			buffer.append(files[i].getAbsolutePath()+files[i].length());
		}
		return buffer.toString();
	}
	
	public static class MakeVideoFolder extends Figure implements ActionListener{
		File dirFile;
		public MakeVideoFolder(File dir){
			super();
			this.dirFile=dir;
			//setLayoutManager(new XYLayout());
			 FlowLayout flow = new FlowLayout(false);
			 setLayoutManager(flow);
			 Label label=new Label(Messages.getString("pssync.psp_video_folder_not_found"));
			 this.add(label);
			// label.setBounds(new Rectangle(0,0,200,100));
			 //
			org.eclipse.draw2d.Button makeVideoButton=new org.eclipse.draw2d.Button(Messages.getString("pssync.psp_video_folder_make"));
			makeVideoButton.addActionListener(this);
			//makeVideoButton.setBounds(new Rectangle(0,120,200,100));
			 //Label makeVideoButton=new Label(Messages.getString("pssync.psp_video_folder_make"));
			 //makeVideoButton.setBorder(new FrameBorder());
			 this.add(makeVideoButton);
		}
		public void actionPerformed(ActionEvent arg0) {
			new File(dirFile,"VIDEO").mkdir();
		}
		
	
	}
	public class AutoPSPVideoDirectoryOpener extends Thread{
		public void run(){
			while(monitorPSPDirectory){//fore ever;
				try{
				if(!executing){//only check if not executing.
				File dir=PSPUtils.findPSPDrive();
				if(dir==null){
					lastPSPDirectoryInfo="";
					PlatformUI.getWorkbench().getDisplay().asyncExec(new UpdatePSPFigure(new Label(Messages.getString("pssync.psp_not_found")),false));
					
					updatePSPDir(null,false);
				}else{
					if(PSPUtils.existVideoFolder(dir)){
						updatePSPDir(dir,true);
					}else{
						lastPSPDirectoryInfo="";
						
						//SyncExec make a freeze.especially initialize
						PlatformUI.getWorkbench().getDisplay().asyncExec(new UpdatePSPFigure(new MakeVideoFolder(dir),false));
						updatePSPDir(null,false);
					}
				}
				}
				try {
					Thread.sleep(pspMonitorSleeptime);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				}catch(Exception e2){//dont stop monitor action
					e2.printStackTrace();
					pspMonitorSleeptime+=100;//for forever loop
				}
			}
		}
	}
	
	public class AutoHDDirectoryOpener extends Thread{
		public void run(){
			while(monitorHDDirectory){//fore ever;
				try{
				try {
					Thread.sleep(hdMonitorSleeptime);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if(!executing){//only check if not executing.
				File dir=hdDir;
				if(dir==null || !dir.exists()){
					lastHDDirectoryInfo="";
					noHDDirectory();
					
				}else{
					List fileList=new ArrayList();
					String list[]=dir.list(new MP4FilenameFilter());
					File[] files;
					if(list==null){
						log.warn("file.lise()==null:"+dir);
						files=new File[0];
					}else{
					for (int i = 0; i < list.length; i++) {
						File mp4File=new File(dir,list[i]);
						if(mp4File.length()>0){//for valid mp4
							fileList.add(mp4File);
						}
					}
					
					files=(File[])fileList.toArray(new File[fileList.size()]);
					}
					String info=toDirectoryInfo(dir,files);
					
					if(!lastHDDirectoryInfo.equals(info)){
						lastHDDirectoryInfo=info;
						updateHDFiles(dir, files,true);
						}
					}
				}
				
			
			}catch(Exception e2){//dont stop monitor action
				e2.printStackTrace();
				hdMonitorSleeptime+=100;//for forever loop
			}
			}
		}
	}
	
	public class UpdateHDFigure extends Thread{
		Figure replace;
		boolean keepselect;
		public UpdateHDFigure(Figure replace,boolean keepselect){
			this.keepselect=keepselect;
			this.replace=replace;
		}
		
		public void run(){
			if(keepselect){
				HashMap selectionMap=new HashMap();
				MP4ThumbnailFigure oldSelection[]=getHDMP4Figure();
				//store data
				for (int i = 0; i < oldSelection.length; i++) {
					File mp4=oldSelection[i].getMp4File();
					String key=mp4.getAbsolutePath()+mp4.length();
					String value=oldSelection[i].isSelection()+","+oldSelection[i].getAction();
					//log.info(key+","+value);
					selectionMap.put(key,value);
				}
				
				//restore data
				Iterator iter=replace.getChildren().iterator();
				while(iter.hasNext()){
					MP4ThumbnailFigure figure=(MP4ThumbnailFigure) iter.next();
					File mp4=figure.getMp4File();
					String v=(String) selectionMap.get(mp4.getAbsolutePath()+mp4.length());
					if(v!=null){
						
						String boolen_int[]=v.split(",");
						figure.setSelection(Boolean.parseBoolean(boolen_int[0]));
						figure.setAction(Integer.parseInt(boolen_int[1]));
						//log.info("setValue:"+mp4.getName()+" "+boolen_int[0]+","+boolen_int[1]);
						
					}
				}
				
			}
			
			hdListFigure=replace;
			
			hdFigure.removeAll();
			if(replace!=null){
				hdFigure.add(replace);
			}
			hdFigure.repaint();
		}
	}
	
	public class UpdatePSPFigure extends Thread{
		boolean keepselect;
		Figure replace;
		public UpdatePSPFigure(Figure replace,boolean keepselect){
			this.keepselect=keepselect;
			this.replace=replace;
		}
		
		public void run(){
			log.trace("UpdatePSPFigure run()");
			/*
			 * for debug
			if(pspListFigure!=null && replace==null){
				throw new RuntimeException();
			}
			*/
			if(keepselect && replace!=null){
				//log.info("keep:"+pspListFigure);
				HashMap selectionMap=new HashMap();
				MP4ThumbnailFigure oldSelection[]=getPSPMP4Figures();
				//store data
				for (int i = 0; i < oldSelection.length; i++) {
					File mp4=oldSelection[i].getMp4File();
					String key=mp4.getAbsolutePath()+mp4.length();
					String value=oldSelection[i].isSelection()+","+oldSelection[i].getAction();
					//log.info(key+","+value);
					selectionMap.put(key,value);
				}
				
				//restore data
			
				if(!(replace instanceof MakeVideoFolder)){
				//TODO list only
				Iterator iter=replace.getChildren().iterator();
				while(iter.hasNext()){
					MP4ThumbnailFigure figure=(MP4ThumbnailFigure) iter.next();
					File mp4=figure.getMp4File();
					String v=(String) selectionMap.get(mp4.getAbsolutePath()+mp4.length());
					if(v!=null){
						
						String boolen_int[]=v.split(",");
						figure.setSelection(Boolean.parseBoolean(boolen_int[0]));
						figure.setAction(Integer.parseInt(boolen_int[1]));
						//log.info("setValue:"+mp4.getName()+" "+boolen_int[0]+","+boolen_int[1]);
						
					}
				}
				}
				
			}
			
			pspListFigure=replace;
			
			pspFigure.removeAll();
			if(replace!=null){
				pspFigure.add(replace);
			}
			pspFigure.repaint();
		}
	}
	
	public void noHDDirectory(){
		//TODO no directory
		hdDir=null;
		PlatformUI.getWorkbench().getDisplay().syncExec(new UpdateHDFigure(new Label(Messages.getString("pssync.directory_not_found")),false));
		
	}
	public void openHDDirectory(File file){
		if(file!=null && file.exists()){
			hdDir=file;
			
		}else{
			noHDDirectory();
//			return;
		}
		
		//make thumb
		List fileList=new ArrayList();
		File[] files;
		String list[]=file.list(new MP4FilenameFilter());
		if(list==null){
			log.warn("file.lise()==null:"+file);
			files= new File[0];
		}else{
		for (int i = 0; i < list.length; i++) {
			File mp4File=new File(file,list[i]);
			if(mp4File.length()>0){//for valid mp4
				fileList.add(mp4File);
			}
		}
		
		files=(File[])fileList.toArray(new File[fileList.size()]);
		}
		
		lastHDDirectoryInfo=toDirectoryInfo(file,files);
		updateHDFiles(file,files,false);
		
		//update infos(thread)
		
		PlatformUI.getWorkbench().getDisplay().syncExec(new SetFreeSpace(file,hdInfo));
		
	}
	
	
	
	public Image loadMP4Image(File mp4){
		Image img=noImage;
		try{
		File imgFile=new File(FileNameUtils.getChangedExtensionName(mp4, "jpg",true));
		if(imgFile.exists() && imgFile.length()>0){
			try{
				img=new Image(null,imgFile.getAbsolutePath());
				//check size;
				if(img.getBounds().width!=160 || img.getBounds().height!=120){//fix value
					img=ImageUtils.createThumbnail(img, 160, 120);
				}
			}catch(Exception e){
				log.warn("unsupported image:"+imgFile);
				img=noImage;
			}
		}else{
			ThumbnailManager.makeThumbnail(mp4, 1, imgFile);//TODO control time
			if(imgFile.exists()){
				try{
					img=new Image(null,imgFile.getAbsolutePath());
				}catch(Exception e){
					e.printStackTrace();
					log.warn("unsupported image:"+imgFile);
					img=noImage;
				}
			}
		}}catch(Exception e){
			e.printStackTrace();
			log.warn(e.getMessage());
			img=noImage;
		}
		return img;
	}
	
	private  void updatePSPFiles(File parent, File[] files,boolean keepselect) {
	
		log.trace(parent+","+keepselect);
		pspDir=parent;
		//log.info("update:"+parent);
		pspMP4Files=files;
		
		//what f*
		//PlatformUI.getWorkbench().getDisplay().syncExec(new UpdatePSPFigure(null,keepselect));
		
		
		Figure tmpFigure=new Figure();//avoid dublicate 
		tmpFigure.setLayoutManager(new CustomLayout(pspCanvas,pspFigure));
		for (int i = 0; i < files.length; i++) {
			
			Image img=loadMP4Image(files[i]);
			
			MP4ThumbnailFigure figure=new MP4ThumbnailFigure(files[i],img);
			//TODO set something for PSP
			tmpFigure.add(figure);
		}
		
		
		
		PlatformUI.getWorkbench().getDisplay().syncExec(new UpdatePSPFigure(tmpFigure,keepselect));
	}
	
	public MP4ThumbnailFigure[] getPSPMP4Figures(){
		if(pspListFigure!=null && !(pspListFigure instanceof MakeVideoFolder)){
			return (MP4ThumbnailFigure[]) pspListFigure.getChildren().toArray(new MP4ThumbnailFigure[0]);
			
		}else{
			return new MP4ThumbnailFigure[0];
		}
	}
	
	public MP4ThumbnailFigure[] getHDMP4Figure(){
		if(hdListFigure!=null){
			return (MP4ThumbnailFigure[]) hdListFigure.getChildren().toArray(new MP4ThumbnailFigure[0]);
			
		}else{
			return new MP4ThumbnailFigure[0];
		}
	}
	
	private void updateHDFiles(File parent, File[] files,boolean keepSelection) {
		//keep figure files.
		
		log.info("hd updated:"+parent);
		hdMP4Files=files;
		//PlatformUI.getWorkbench().getDisplay().syncExec(new UpdateFigure(hdFigure,null));
		//hdFigure.removeAll();
		//hdFigure.repaint();
		
		Figure tmpFigure=new Figure();
		tmpFigure.setLayoutManager(new CustomLayout(hdCanvas,hdFigure));
		for (int i = 0; i < files.length; i++) {
			//log.info(files[i]);
			//log.info(imgFile.getAbsolutePath());
			Image img=loadMP4Image(files[i]);
			MP4ThumbnailFigure figure=new MP4ThumbnailFigure(files[i],img);
			figure.setOnHD(true);
//			TODO set something for HD
			tmpFigure.add(figure);
		}

		PlatformUI.getWorkbench().getDisplay().asyncExec(new UpdateHDFigure(tmpFigure,keepSelection));
		PlatformUI.getWorkbench().getDisplay().asyncExec(new UpdateSelection());
		
	}

	public void openPSPVideoDirectory(File file){
		//TODO
		//update infos(thread)
	}
	
	public void setFocus() {
		
	}
	

	public void cancel(){
		
		if(currentCommand!=null){
			currentCommand.setCanceld(true);//cancel
		}
		
		executing=false;
		//update
		updatePSPDir(pspDir.getParentFile(),false);//pspDir has VIDEO
		openHDDirectory(hdDir);
		enableWidgets();
	}
	
	public void sync(){
		executing=true;
		disableWidgets();
		
		PlatformUI.getWorkbench().getDisplay().asyncExec(new StatusBarUtils.ShowStatusBar(""));//clear message
		progressMonitor=ProgressMonitorUtils.getProgressMonitor();
		new Sync(getCommands()).start();
		//TODO
		//copy video from psp to hd
		//copy video from hd to psp
	}
	
	public long getFreeSpace(File dir) throws IOException{
		if(dir==null || !dir.exists()){
			return 0;
		}
		
		
			return FileSystemUtils.freeSpaceKb(dir.getAbsolutePath())*1024;
		
	}
	
	public class Sync extends Thread{
		PSPIOCommand[] commands;
		public Sync(PSPIOCommand[] commands){
			this.commands=commands;
		}
		
		
		public void run(){
			//set progress.
			ProgressMonitorUtils.beginMonitor(progressMonitor, "", commands.length, false);
			for (int i = 0; i < commands.length; i++) {
				if(!executing){//canceld;
					PlatformUI.getWorkbench().getDisplay().syncExec(new SyncCanceled());
					return;
				}
				//check freespace
				try {
				if(commands[i].isPSPSrc()){
					
					if(!availableCommand(commands[i],getFreeSpace(hdDir))){
						log.warn("no space");
						PlatformUI.getWorkbench().getDisplay().syncExec(new SyncCanceled());
						return;
						//TODO alert.
					}
					}
				else{
					if(!availableCommand(commands[i], getFreeSpace(pspDir))){
						log.warn("no space");
						PlatformUI.getWorkbench().getDisplay().syncExec(new SyncCanceled());
						return;
						//TODO alert.
					}
				}
				}
				 catch (IOException e) {
						// TODO Auto-generated catch block
						PlatformUI.getWorkbench().getDisplay().syncExec(new SyncCanceled());
						e.printStackTrace();
						return;
					}
				
				
				//exec
				 log.info(commands[i]);
				 currentCommand=commands[i];
				 
				 if(!executing){//canceld;
						PlatformUI.getWorkbench().getDisplay().syncExec(new SyncCanceled());
						return;
					}
				 int result=commands[i].execCommand();
				 log.info("done command");
				 if(result!=0){
					 log.warn("execute faild:"+result);
					
					PlatformUI.getWorkbench().getDisplay().asyncExec(new StatusBarUtils.ShowStatusBar("error:"+result));
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}//show error;
					PlatformUI.getWorkbench().getDisplay().syncExec(new SyncCanceled());
					ProgressMonitorUtils.doneMonitor(progressMonitor,false);
					return;
				 }else{
					 ProgressMonitorUtils.workedMonitor(progressMonitor,1,false);
				 }
				
				 //check err and do something.
			}
			
			ProgressMonitorUtils.doneMonitor(progressMonitor,false);
			//done
			PlatformUI.getWorkbench().getDisplay().syncExec(new SyncFinished());
		}
	}
	
	public class SyncCanceled extends Thread{
		public void run(){
			log.info("canceled");
			cancel();
		}
	}
	
	public class SyncFinished extends Thread{
		public void run(){
			log.info("finished");
			
			
			//TODO update both dir.
			if(pspDir!=null && pspDir.exists()){
				updatePSPDir(pspDir.getParentFile(),false);//pspDir has VIDEO
			}
			openHDDirectory(hdDir);
			enableWidgets();
			executing=false;
		}
	}
	
	public void disableWidgets(){
		syncButton.setText(Messages.getString("pspsync.cancel"));
		directoryPaths.setEnabled(false);
		pspDirPath.setEnabled(false);
		
		
		//pspCanvas.setEnabled(false);
		//hdCanvas.setEnabled(false);
	}
	public void enableWidgets(){
		syncButton.setText(Messages.getString("pspsync.exec"));
		directoryPaths.setEnabled(true);
		pspDirPath.setEnabled(true);
		//pspCanvas.setEnabled(true);
		//hdCanvas.setEnabled(true);
	}
	
	public class MP4FilenameFilter implements FilenameFilter{

		public boolean accept(File arg0, String arg1) {
			return arg1.toLowerCase().endsWith(".mp4");
		}
		
	}
	
	public static boolean existFile(File target,File list[]){
		
		for (int i = 0; i < list.length; i++) {
			if(target.getName().toLowerCase().equals(list[i].getName().toLowerCase())){
				return true;
			}
		}
		return false;
	}

	public class MP4ThumbnailFigure extends Panel {
		MP4ThumbnailFigure self;
		Label titleLabel;
		Label imageLabel;
		boolean selection;
		
		LineBorder lineBorder; 
		MarginBorder marginBorder;
		File mp4File;
		
		private int action;
		
		CutomLabel actionLabel;
		boolean onHD;
		public long getFileSize(){
			return mp4File.length();
		}
		public String trimTitle(String name) {
			return name.substring(0, Math.min(16, name.length()));
		}
		
		public void setDefaultAction(){
			//set default value
			if(onHD){
//				TODO change can set default action
			//to PSP
			if(action==ACTION_NONE){//set default only
				if(isPSPDirectoryAvailable()){
					if(existFile(self.mp4File,pspMP4Files)){
						setAction(ACTION_COPY_OVERWRITE);//there are already file
					}else{
						setAction(ACTION_COPY);//
					}
					
				}
			}
			}else{
			//to HD
				//TODO change can set default action
				if(action==ACTION_NONE){//set default only
					if(isHDDirectoryAvailable()){
						if(existFile(self.mp4File,hdMP4Files)){
							setAction(ACTION_DELETE);//no need.
						}else{
							setAction(ACTION_MOVE);// move back
						}
						
					}
				}
			}
			
		}
		
		public void setSelection(boolean bool){
			if(this.selection!=bool){
			this.selection=bool;
			if(selection){
				self.setDefaultAction();
				actionLabel.setVisible(true);
				this.setBorder(lineBorder);
			}else{
				actionLabel.setVisible(false);
				this.setBorder(marginBorder);
			}
			repaint();
			}
		}
		public boolean isSelection(){
			return selection;
		}
		public void turnSelection(){
			setSelection(!selection);
		}
		public void setImage(Image img) {
			if (img != null) {
				imageLabel.setIcon(img);
			} else {
				log.info("setimage:" + getLabel());
			}
		}

		public String getLabel() {
			return titleLabel.getText();
		}

		public void setLabel(String text) {
			titleLabel.setText(text);
		}

		
		
		public MP4ThumbnailFigure(File mp4File, Image img) {
			super();
			self=this;
			this.mp4File=mp4File;
			this.setLayoutManager(new FlowLayout(false));
			imageLabel = new Label(img);
			imageLabel.setToolTip(new Label(toTooltip()));
			imageLabel.setLayoutManager(new StackLayout());
		
			add(imageLabel);
			
			actionLabel=new CutomLabel();
			actionLabel.setVisible(false);
			imageLabel.add(actionLabel);
			
			titleLabel = new Label(trimTitle(mp4File.getName()));
			add(titleLabel);
			addMouseListener(new org.eclipse.draw2d.MouseListener() {

			

				
					
					public void mousePressed(org.eclipse.draw2d.MouseEvent mouseEvent) {
					
					}
				
				
					public void mouseReleased(org.eclipse.draw2d.MouseEvent mouseEvent) {
					
					if(self.isOnHD()){
						hdMovieActionPopup.setTargetFigure(self);
						if(executing){
							hdMovieActionPopup.setCopyEnabled(false);
							hdMovieActionPopup.setMoveEnabled(false);
							hdMovieActionPopup.setCopyOverwriteEnabled(false);
							hdMovieActionPopup.setMoveOverwriteEnabled(false);
							hdMovieActionPopup.setDeleteEnabled(false);
						}else{
						if(isPSPDirectoryAvailable()){
							if(existFile(self.mp4File,pspMP4Files)){
								hdMovieActionPopup.setCopyEnabled(false);
								hdMovieActionPopup.setMoveEnabled(false);
								hdMovieActionPopup.setCopyOverwriteEnabled(true);
								hdMovieActionPopup.setMoveOverwriteEnabled(true);
								hdMovieActionPopup.setDeleteEnabled(true);
							}else{
								hdMovieActionPopup.setCopyEnabled(true);
								hdMovieActionPopup.setMoveEnabled(true);
								hdMovieActionPopup.setCopyOverwriteEnabled(false);
								hdMovieActionPopup.setMoveOverwriteEnabled(false);
								hdMovieActionPopup.setDeleteEnabled(true);
							}
						}else{
							hdMovieActionPopup.setCopyEnabled(false);
							hdMovieActionPopup.setMoveEnabled(false);
							hdMovieActionPopup.setCopyOverwriteEnabled(false);
							hdMovieActionPopup.setMoveOverwriteEnabled(false);
							hdMovieActionPopup.setDeleteEnabled(true);
						}
						}
					}else{
						pspMovieActionPopup.setTargetFigure(self);
						if(executing){
							pspMovieActionPopup.setCopyEnabled(false);
							pspMovieActionPopup.setMoveEnabled(false);
							pspMovieActionPopup.setCopyOverwriteEnabled(false);
							pspMovieActionPopup.setMoveOverwriteEnabled(false);
							pspMovieActionPopup.setDeleteEnabled(false);
						}else{
							
						
						if(isHDDirectoryAvailable()){
							if(existFile(self.mp4File,hdMP4Files)){
								pspMovieActionPopup.setCopyEnabled(false);
								pspMovieActionPopup.setMoveEnabled(false);
								pspMovieActionPopup.setCopyOverwriteEnabled(true);
								pspMovieActionPopup.setMoveOverwriteEnabled(true);
								pspMovieActionPopup.setDeleteEnabled(true);
							}else{
								pspMovieActionPopup.setCopyEnabled(true);
								pspMovieActionPopup.setMoveEnabled(true);
								pspMovieActionPopup.setCopyOverwriteEnabled(false);
								pspMovieActionPopup.setMoveOverwriteEnabled(false);
								pspMovieActionPopup.setDeleteEnabled(true);
							}
						}else{
							pspMovieActionPopup.setCopyEnabled(false);
							pspMovieActionPopup.setMoveEnabled(false);
							pspMovieActionPopup.setCopyOverwriteEnabled(false);
							pspMovieActionPopup.setMoveOverwriteEnabled(false);
							pspMovieActionPopup.setDeleteEnabled(true);
						}
						}
					}
					if(executing){
						return;//do nothing anymore
					}
					
					if(mouseEvent.button==1){
					if((mouseEvent.getState() & InputEvent.CONTROL)>0){
						turnSelection();
					}else if((mouseEvent.getState() & InputEvent.SHIFT)>0){
						//
						//selectBetween(selectFirst,currentFile);
					}else{
						//unselectAll();
						turnSelection();
					}
					}else if(mouseEvent.button==3){
						//do nothing when right click
						//setSelection(true);
					}
					
					//unselect other
					unselectOposite();
					
					updateSelection();
				}

			

				public void mouseDoubleClicked(
						org.eclipse.draw2d.MouseEvent arg0) {
					//playFile(toFile());
					
				}

			});
			
			
			lineBorder = new LineBorder();
			lineBorder.setColor(ColorConstants.green);
			lineBorder.setWidth(2);
			
			marginBorder=new MarginBorder(2);
			this.setBorder(marginBorder);

		}
		
		public String toTooltip(){
			
			
			int kbyte=(int)(mp4File.length()/1024);
			String label=mp4File.getAbsolutePath();
			label+="\n\n"+kbyte+" KBytes\n";
			label+=new Date(mp4File.lastModified()).toLocaleString();//TODO change someday
			return label;
		}
		
		public void unselectOposite(){
			if(self.isSelection()){
				if(self.getAction()!=ACTION_NONE && self.getAction()!=ACTION_DELETE){
					if(self.isOnHD()){
						if(existFile(self.mp4File,pspMP4Files)){
							MP4ThumbnailFigure other=findPSPFigure(new File(pspDir,self.getMp4File().getName()));
							if(other!=null && other.isSelection()){
								other.setSelection(false);
							}
						}
					}else{
						if(existFile(self.mp4File,hdMP4Files)){
							MP4ThumbnailFigure other=findHDFigure(new File(hdDir,self.getMp4File().getName()));
							if(other!=null && other.isSelection()){
								other.setSelection(false);
							}
						}
					}
				}
			}
		}
		
		public String toTooltip(String path){
			
			int kbyte=(int)(mp4File.length()/1024);
			String label=mp4File.getName();
			label+="\n\n"+kbyte+" KBytes\n";
			label+=new Date(mp4File.lastModified()).toLocaleString();//TODO change someday
			return label;
		}
		/*
		public void unselectAll(){
			
			Figure figures[]=(Figure[]) this.getParent().getChildren().toArray(new Figure[0]);
			//log.info("figures:"+figures.length);
			for (int i = 0; i < figures.length; i++) {
				if(figures[i] instanceof ThumbnailFigure){
					//log.info("unselect");
					if(figures[i]!=this){
					((ThumbnailFigure)figures[i]).setSelection(false);
					}
				}
			}
		}

		public void selectAll(){
			
			Figure figures[]=(Figure[]) this.getParent().getChildren().toArray(new Figure[0]);
			//log.info("figures:"+figures.length);
			for (int i = 0; i < figures.length; i++) {
				if(figures[i] instanceof ThumbnailFigure){
					//log.info("unselect");
					//if(figures[i]!=this){
					((ThumbnailFigure)figures[i]).setSelection(true);
				//	}
				}
			}
		}*/

		public int getAction() {
			return action;
		}

		public void setAction(int action) {
			this.action = action;
			actionLabel.setForegroundColor(ColorConstants.black);
			switch(action){
			case ACTION_COPY:
				actionLabel.setText(LABEL_ACTION_COPY);
				break;
			case ACTION_MOVE:
				actionLabel.setText(LABEL_ACTION_MOVE);
				break;
			case ACTION_COPY_OVERWRITE:
				actionLabel.setText(LABEL_ACTION_COPY_OVERWRITE);
				break;
			case ACTION_MOVE_OVERWRITE:
				actionLabel.setText(LABEL_ACTION_MOVE_OVERWRITE);
				break;
			case ACTION_DELETE:
				actionLabel.setForegroundColor(ColorConstants.red);
				actionLabel.setText(LABEL_ACTION_DELETE);
				
				break;
			}
			unselectOposite();
			updateSelection();
		}

		public boolean isOnHD() {
			return onHD;
		}

		public void setOnHD(boolean onHD) {
			this.onHD = onHD;
		}
		public File getMp4File() {
			return mp4File;
		}
		public void setMp4File(File mp4File) {
			this.mp4File = mp4File;
		}

	
	}
	
	
	
	
	public class CustomLayout implements LayoutManager {
		Figure control;
		FigureCanvas canvas;
		public CustomLayout(FigureCanvas canvas,Figure control) {
			this.canvas=canvas;
			this.control = control;

		}

		public Object getConstraint(IFigure child) {
			// TODO Auto-generated method stub
			return null;
		}

		public Dimension getMinimumSize(IFigure container, int wHint, int hHint) {
			// log.info(container+" minimumsize:"+"whint="+wHint+"
			// hHint="+hHint);
			// log.info("parent:"+control.getSize());
			return getPreferredSize(container, wHint, hHint);
		}

		public Dimension getPreferredSize(IFigure container, int wHint,
				int hHint) {
			 //log.info(container+" preferedsize:"+"whint="+wHint+" hHint="+hHint);
			// log.info("parent:"+control.getSize());
			layout(container);
			Figure figures[] = (Figure[]) container.getChildren().toArray(
					new Figure[0]);
			int my = 0;
			for (int i = 0; i < figures.length; i++) {
				my = Math.max(my, figures[i].getLocation().y
						+ figures[i].getSize().height);

			}
			//log.info("my="+my);
			return new Dimension(control.getClientArea().x, my);
		}

		public void invalidate() {
			// log.info("invalidate");
		}

		public void layout(IFigure container) {
			
			Figure figures[] = (Figure[]) container.getChildren().toArray(
					new Figure[0]);
			int space = 1;
			int dx = 0;
			int dy = 0;
			int preHeight = 0;
			if (control.getSize().width == 0 && control.getSize().height == 0) {
				return;
			}
			for (int i = 0; i < figures.length; i++) {
				Dimension d = figures[i].getPreferredSize();
				if (dx == 0) {//row 1
					figures[i].setLocation(new Point(dx, dy));
					figures[i].setSize(d.width, d.height);
					dx += d.width + space;
					preHeight = d.height + space;
				} else {
					
					int sc = 0;//scrollbar showed
					if (!canvas.getVerticalBar().isEnabled()) {
						sc = 16;//no scrollbar
					}
					//log.info("scroll:"+sc);
					if (dx + d.width > control.getClientArea().width - sc) {// for
						// scroll
						// bar
						dx = 0;
						dy += preHeight;
					}
					figures[i].setLocation(new Point(dx, dy));
					figures[i].setSize(d.width, d.height);
					//log.info(i+":"+figures[i].getBounds());
					dx += d.width + space;
					preHeight = d.height + space;
				}

			}
			int my = 0;
			for (int i = 0; i < figures.length; i++) {
				my = Math.max(my, figures[i].getLocation().y
						+ figures[i].getSize().height);

			}
			
			//relayout with scrollbar
			if(my>control.getClientArea().height){
				dx = 0;
				dy = 0;
				preHeight = 0;
				for (int i = 0; i < figures.length; i++) {
					Dimension d = figures[i].getPreferredSize();
					if (dx == 0) {//row 1
						figures[i].setLocation(new Point(dx, dy));
						figures[i].setSize(d.width, d.height);
						dx += d.width + space;
						preHeight = d.height + space;
					} else {
						
						int sc = 16;//scrollbar showed
						
						
						if (dx + d.width > control.getClientArea().width - sc) {// for
							// scroll
							// bar
							dx = 0;
							dy += preHeight;
						}
						figures[i].setLocation(new Point(dx, dy));
						figures[i].setSize(d.width, d.height);
						//log.info(i+":"+figures[i].getBounds());
						dx += d.width + space;
						preHeight = d.height + space;
					}

				}
				
			}
			
			
			// control.revalidate();//is OK?
			// container.setSize(control.getClientArea().width,my);
		}

		public void remove(IFigure child) {

		}

		public void setConstraint(IFigure child, Object constraint) {
			// TODO Auto-generated method stub

		}

	}
	
	public class CutomLabel extends Figure{
		private String text="";
		
		protected void paintFigure(Graphics graphics) {
			if(text.length()>0){
			Rectangle rect=getBounds();
			//graphics.fillRectangle(rect);
			TextLayout layout=new TextLayout(null);
			layout.setText(text);
			int textHeight=20;
			
			int cy=(rect.height)/2;
			graphics.fillRectangle(rect.x,rect.y+cy-textHeight/2,rect.width,textHeight);
			
			layout.setWidth(rect.width);
			
			layout.setAlignment(SWT.CENTER);
			
			
			graphics.drawTextLayout(layout, rect.x,rect.y+cy-8);//take it easy
			}
		}
		public String getText() {
			return text;
		}
		public void setText(String text) {
			this.text = text;
			repaint();
		}
	}
	public class MovieActionPopup {
		private Menu rootMenu;
		private MP4ThumbnailFigure targetFigure;
		private MenuItem copyItem;
		private MenuItem moveItem;
		private MenuItem copyOverwriteItem;
		private MenuItem moveOverwriteItem;
		private MenuItem deleteItem;
		private MenuItem playItem;
		private boolean hdDirectory;
		private MenuItem openItem;
	
		public void setCopyEnabled(boolean bool){
			copyItem.setEnabled(bool);
		}
		public void setPlayEnabled(boolean bool) {
			playItem.setEnabled(bool);
		}
		public void setOpenEnabled(boolean bool) {
			openItem.setEnabled(bool);
		}
		public void setMoveEnabled(boolean bool){
			moveItem.setEnabled(bool);
		}
		public void setCopyOverwriteEnabled(boolean bool){
			copyOverwriteItem.setEnabled(bool);
		}
		public void setMoveOverwriteEnabled(boolean bool){
			moveOverwriteItem.setEnabled(bool);
		}
		public void setDeleteEnabled(boolean bool){
			deleteItem.setEnabled(bool);
		}
		public MovieActionPopup(Control arg0) {
		
			rootMenu=new Menu(arg0);
			copyItem = new MenuItem(rootMenu, SWT.PUSH);
			copyItem.setText(LABEL_ACTION_COPY);
			copyItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					targetFigure.setSelection(true);
					targetFigure.setAction(ACTION_COPY);
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
			moveItem = new MenuItem(rootMenu, SWT.PUSH);
			moveItem.setText(LABEL_ACTION_MOVE);
			moveItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					targetFigure.setSelection(true);
					targetFigure.setAction(ACTION_MOVE);
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
			copyOverwriteItem = new MenuItem(rootMenu, SWT.PUSH);
			copyOverwriteItem.setText(LABEL_ACTION_COPY_OVERWRITE);
			copyOverwriteItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					targetFigure.setSelection(true);
					targetFigure.setAction(ACTION_COPY_OVERWRITE);
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
			moveOverwriteItem = new MenuItem(rootMenu, SWT.PUSH);
			moveOverwriteItem.setText(LABEL_ACTION_MOVE_OVERWRITE);
			moveOverwriteItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					targetFigure.setSelection(true);
					targetFigure.setAction(ACTION_MOVE_OVERWRITE);
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
			new MenuItem(rootMenu,SWT.SEPARATOR);
			deleteItem = new MenuItem(rootMenu, SWT.PUSH);
			deleteItem.setText(LABEL_ACTION_DELETE);
			deleteItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					targetFigure.setSelection(true);
					targetFigure.setAction(ACTION_DELETE);
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
			new MenuItem(rootMenu,SWT.SEPARATOR);
			
			playItem = new MenuItem(rootMenu, SWT.PUSH);
			playItem.setText(LABEL_ACTION_PLAY);
			playItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					Program p=Program.findProgram(".mp4");
					if(p!=null){
						p.execute(targetFigure.getMp4File().getAbsolutePath());
					}
					
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
		
			openItem = new MenuItem(rootMenu, SWT.PUSH);
			openItem.setText(LABEL_ACTION_OPEN);
			openItem.addSelectionListener(new SelectionListener() {

				public void widgetSelected(SelectionEvent e) {
					//File dir=targetFigure.getMp4File().getParentFile();
					File dir;
					if(isHdDirectory()){
						dir=hdDir;
					}else{
						dir=pspDir;
					}
					Runtime r=Runtime.getRuntime();
					
						try {
							r.exec(new String[]{"explorer",dir.getAbsolutePath()});
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
					
				}

				public void widgetDefaultSelected(SelectionEvent e) {
				}

			});
			
		}
		
		public Menu getRootMenu() {
			return rootMenu;
		}
		public void setRootMenu(Menu rootMenu) {
			this.rootMenu = rootMenu;
		}
		public MP4ThumbnailFigure getTargetFigure() {
			return targetFigure;
		}
		public void setTargetFigure(MP4ThumbnailFigure targetFigure) {
			this.targetFigure = targetFigure;
		}
		public boolean isHdDirectory() {
			return hdDirectory;
		}
		public void setHdDirectory(boolean hdDirectory) {
			this.hdDirectory = hdDirectory;
		}
		
	}

	public class ResizeMonitor implements ControlListener {
		Figure figure;

		public ResizeMonitor(Figure figure) {
			this.figure = figure;
		}

		public void controlMoved(ControlEvent e) {

		}

		public void controlResized(ControlEvent e) {
			
			figure.revalidate();// i don't know.i have any other idea.
			
		}

	}
	
	 public void dispose() {
		 monitorPSPDirectory=false;
		 monitorHDDirectory=false;
		 super.dispose();
		 
	 }
	 
		private void updateExplorerPaths() {
			String paths=Akj_betasPlugin.getDefault().getPreferenceStore().getString(FLVToolsPage.EXPLORER_PATHS);
			String path[]=paths.split(";");//one day should change for other platform.
			directoryPaths.removeAll();
			
			for (int i = 0; i < path.length; i++) {
				directoryPaths.add(path[i]);
			}
			
			directoryPaths.removeSelectionListener(explorerPathChange);
			
			if(hdDir==null){
				directoryPaths.select(0);
			}else{
				boolean find=false;
				for (int i = 0; i < path.length; i++) {
					if(path[i].equals(hdDir.getAbsolutePath())){
						directoryPaths.select(i);
						find=true;
						break;
					}
				}
				if(!find){
					if(hdDir!=null){//something wrong?
					directoryPaths.add(hdDir.getAbsolutePath());
					directoryPaths.select(directoryPaths.getItemCount()-1);
					}
				}
			}
			
			directoryPaths.addSelectionListener(explorerPathChange);
			
			
		}
		
		public class ExplorerPathChange implements SelectionListener {

			public void widgetSelected(SelectionEvent e) {
				String dir=directoryPaths.getItem(directoryPaths.getSelectionIndex());
				openHDDirectory(new File(dir));
				
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

		}
		
		public class SettingMonitor implements IPropertyChangeListener {

			public void propertyChange(PropertyChangeEvent event) {
				log.info(event.getProperty());
				if (event.getProperty().equals(FLVToolsPage.EXPLORER_PATHS)) {
					updateExplorerPaths();
				}
			}

			

		}
		
}